﻿using ArtMath.Attribute;
using ArtMath.Component.Point;
using ArtMath.Core.Data;
using ArtMath.PointCollection;
using ArtMath.Resource;
using System;
using System.Collections.Generic;

namespace ArtMath.Component.ConicalSection
{
    /// <summary>
    /// 焦点定点椭圆
    /// </summary>
    [Serializable]
    public class FocusPointEllipse : EllipseBase
    {
        double c;
        public FocusPointEllipse(SketchPad pad, string name, bool addToList = true) : base(pad, name, ToolTypeName.jdddty, addToList)
        {
            InPoints = new PointBase[3];
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("{0}1", "Focus")]
        public PointBase FocusPoint1
        {
            get { return InPoints[0]; }
            set { SetPoint(0, value); }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("{0}2", "Focus")]
        public PointBase FocusPoint2
        {
            get { return InPoints[1]; }
            set { SetPoint(1, value); }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("PointOnEllipse")]
        public PointBase PointOnEllipse
        {
            get { return InPoints[2]; }
            set { SetPoint(2, value); }
        }
        public override PointD Focus1
        {
            get
            {
                if (FocusPoint1 != null) return FocusPoint1.ToPointD();
                return base.Focus1;
            }
        }
        public override PointD NewFocus1
        {
            get
            {
                if (FocusPoint1 != null) return FocusPoint1.NewXY;
                return base.NewFocus1;
            }
        }
        public override PointD PFocus1
        {
            get
            {
                if (FocusPoint1 != null) return FocusPoint1.Pxy;
                return base.PFocus1;
            }
        }
        public override PointD Focus2
        {
            get
            {
                if (FocusPoint2 != null) return FocusPoint2.ToPointD();
                return base.Focus2;
            }
        }
        public override PointD NewFocus2
        {
            get
            {
                if (FocusPoint2 != null) return FocusPoint2.NewXY;
                return base.NewFocus2;
            }
        }
        public override PointD PFocus2
        {
            get
            {
                if (FocusPoint2 != null) return FocusPoint2.Pxy;
                return base.PFocus2;
            }
        }
        public override double FocalHalfLength
        {
            get
            {
                return c;
            }
        }
        public override double NewFocalHalfLength
        {
            get
            {
                return FocusPoint1.NewXY.DistanceTo(FocusPoint2.NewXY) / 2;
            }
        }
        public override PointD NewCenter
        {
            get
            {
                return (FocusPoint1.NewXY + FocusPoint2.NewXY) / 2;
            }
        }
        public override PointD NewPCenter
        {
            get
            {
                return (FocusPoint1.NewPxy + FocusPoint2.NewPxy) / 2;
            }
        }
        public override double NewFocusAngle
        {
            get
            {
                return FocusPoint1.NewXY.GetAngle(FocusPoint2.NewXY);
            }
        }
        public override double NewLongAxisHalfLength
        {
            get
            {
                return (PointOnEllipse.NewXY.DistanceTo(FocusPoint1.NewXY) + PointOnEllipse.NewXY.DistanceTo(FocusPoint2.NewXY)) / 2;
            }
        }
        public override double NewShortAxisHalfLength
        {
            get
            {
                return Math.Sqrt(NewLongAxisHalfLength * NewLongAxisHalfLength - NewFocalHalfLength * NewFocalHalfLength);
            }
        }
        public override bool PointsHaveConstraint
        {
            get { return false; }
        }
        public override void ComponentBuilding(Base component)
        {
            PointD xy = Pad.PxyToXY(SpareCoordinate);
            if (OrderIndex == 0)
            {
                if (FocusPoint1 == null) return;
                if (FocusPoint2 != null)
                {
                    LongAxisHalfLength = (xy.DistanceTo(FocusPoint1.ToPointD()) + xy.DistanceTo(FocusPoint2.ToPointD())) / 2;
                    ShortAxisHalfLength = Math.Sqrt(LongAxisHalfLength * LongAxisHalfLength - c * c);
                }
                else
                {
                    pske.Center = (FocusPoint1.Pxy + SpareCoordinate) / 2;
                    ske.Center = (FocusPoint1.ToPointD() + xy) / 2;
                    c = Center.DistanceTo(xy);
                    FocusAngle = FocusPoint1.ToPointD().GetAngle(xy);
                    ShowStatus($"{Resources.Translate("Creating")}{Resources.ColonSeparate}{Name}{Resources.LeftParenthesis}{Resources.Translate("EllipseCenter")}{Resources.ColonSeparate}{Pad.ShowPoint(Center)}{Resources.CommaSeparate}{Resources.Translate("FocalHalfLength")} = {FocalHalfLength}）");
                    return;
                }
            }
            else
            {
                if (PointOnEllipse == null) return;
                if (FocusPoint1 != null)
                {
                    pske.Center = (FocusPoint1.Pxy + SpareCoordinate) / 2;
                    ske.Center = (FocusPoint1.ToPointD() + xy) / 2;
                    FocusAngle = FocusPoint1.ToPointD().GetAngle(xy);
                    c = Center.DistanceTo(xy);
                    LongAxisHalfLength = (xy.DistanceTo(PointOnEllipse.ToPointD()) + FocusPoint1.DistanceTo(PointOnEllipse)) / 2;
                    ShortAxisHalfLength = Math.Sqrt(LongAxisHalfLength * LongAxisHalfLength - c * c);
                }
                else
                {
                    ShowStatus($"{Resources.Translate("Creating")}{Resources.ColonSeparate}{Name}");
                    return;
                }
            }
            base.ComponentBuilding(component);
        }
        public override void ComponentChanged(ShapeBase component)
        {
            //pske.Center = NewPCenter;
            //ske.Center = NewCenter;
            c = NewFocalHalfLength;
            //ske.RotateAngle = NewFocusAngle;
            //LongAxisHalfLength = NewLongAxisHalfLength;
            //ShortAxisHalfLength = NewShortAxisHalfLength;
            base.ComponentChanged(component);
        }
        public override bool CanDrawVirtual
        {
            get
            {
                if (OrderIndex == 0)
                {
                    if (FocusPoint2 != null)
                    {
                        return true;
                    }
                }
                else
                {
                    if (FocusPoint1 != null)
                    {
                        return true;
                    }
                }
                return false;
            }
        }
        protected override void ClickOrder(IList<PointCreatingArgs> args, int clickTimes, Predicate<PointCreatingArgs> act)
        {
            if (act == null) return;
            if (OrderIndex == 1)
            {
                if (!act(args[2])) return;
                if (!act(args[0])) return;
                if (!act(args[1])) return;
                return;
            }
            base.ClickOrder(args, clickTimes, act);
        }
        public override void CreateComponents()
        {
            if (OrderIndex == 0)
            {
                if (FocusPoint1 == null)
                {
                    FocusPoint1 = Pad.CreatePoint($"{Resources.Translate("Focus")}1", SpareCoordinate_);
                    Pad.TrackObj = this;
                }
                else if (FocusPoint2 == null)
                {
                    FocusPoint2 = Pad.CreatePoint($"{Resources.Translate("Focus")}2", SpareCoordinate_, true, new PointCollectionBase[] { new Universal(FocusPoint1.ToPointD()) });
                }
                else if (PointOnEllipse == null)
                {
                    PointOnEllipse = Pad.CreatePoint(Resources.Translate("PointOnEllipse"), SpareCoordinate_, true, new PointCollectionBase[] { new Universal(FocusPoint1.ToPointD(), FocusPoint2.ToPointD()) });
                    base.CreateComponents();
                }
            }
            else
            {
                if (PointOnEllipse == null)
                {
                    PointOnEllipse = Pad.CreatePoint(Resources.Translate("PointOnEllipse"), SpareCoordinate_);
                    Pad.TrackObj = this;
                }
                else if (FocusPoint1 == null)
                {
                    FocusPoint1 = Pad.CreatePoint($"{Resources.Translate("Focus")}1", SpareCoordinate_, true, new PointCollectionBase[] { new Universal(PointOnEllipse.ToPointD()) });
                }
                else if (FocusPoint2 == null)
                {
                    FocusPoint2 = Pad.CreatePoint($"{Resources.Translate("Focus")}2", SpareCoordinate_, true, new PointCollectionBase[] { new Universal(FocusPoint1.ToPointD(), PointOnEllipse.ToPointD()) });
                    base.CreateComponents();
                }
            }
        }
    }
}